/*
 * i2c.c
 *
 *  Created on: Apr 5, 2016
 *
 */

#include "LPC8xx.h"
#include "utilities.h"
#include "i2c.h"
#include "stdint.h"
#include "gpio.h"
#include "syscon.h"

#define I2CSCL_PIN        P0_10         // P0_10 for I2C0
#define I2CSCL_IOCON_REG  PIO0_10
#define I2CSDA_PIN        P0_11         // P0_11 for I2C0
#define I2CSDA_IOCON_REG  PIO0_11
typedef enum { FALSE = 0, TRUE = !FALSE } Bool;
unsigned char AD7416_SystemError;
unsigned int Temperature; //温度
unsigned char ZorF; //正还是负
//自加的
static __inline _Bool Chip(uint32_t pin)
{
    // LPC_GPIO_PORT->DIR0 &= ~((1<<SDA_PIN)|(1<<SCL_PIN)); // Input GPIOs to input mode 输入模式
    return (_Bool)LPC_GPIO_PORT->B0[pin];
}
void I2C_GPIO_Config(void)
{

    // Enable clock to GPIO0 and pin interrupt modules.
    LPC_SYSCON->SYSAHBCLKCTRL[0] |= (IOCON | GPIO1);
    LPC_SYSCON->SYSAHBCLKCTRL[0] |= GPIO0;   // Turn on clock to GPIO0

    LPC_SWM->PINENABLE0 |= (I2C0_SCL | I2C0_SDA); //I2C0_SDA disabled.  I2C0_SCL disabled.
   /*  // GPIOInit();  //GPIO初始化  有问题   */
    LPC_SYSCON->PRESETCTRL[0] &= (~(1 << 6) & ~(1 << 20)); //(GPIO0_RST_N & GPIOINT_RST_N & GPIO1_RST_N);
    LPC_SYSCON->PRESETCTRL[0] |= ~(~(1 << 6) & ~(1 << 20));



    // Turn on clock to GPIO0
    //LPC_SYSCON->SYSAHBCLKCTRL[0] |= (1<<18|IOCON|GPIO1);//使能SWM和IOCON和GPIO0时钟GPIO1                      加了1<<20
    // (I2CINST|SWM|IOCON);I2C0;
    //ConfigSWM();
    //  LPC_SYSCON->SYSAHBCLKCTRL[0] &= ~1<<7;//不使能SWM时钟  节能



    LPC_IOCON->I2CSCL_IOCON_REG |= 1 << 10; //使P1_14为开漏   pdf 150
    LPC_IOCON->I2CSDA_IOCON_REG |= 1 << 10;//使P1_15为开漏
    I2CSCL_H;
    I2CSDA_H;

    LPC_GPIO_PORT->SET0 = (1 << I2CSCL_PIN) | (1 << I2CSDA_PIN); // PIO0_10 = PIO0_11 = 1
    LPC_GPIO_PORT->DIR0 |= (1 << I2CSCL_PIN) | (1 << I2CSDA_PIN);  // 输出模式

}
/*
void delay_us(int time_us)
{
    int i, j;
    for (i = 0; i < time_us; i++)
    {
        for (j = 0; j < 11; j++);//1us,  zwr4us?
    }
}
void delay_ms(int time_ms)  // zwr 44-48ms * time_ms ?
{
    int i;
    for (i = 0; i < time_ms; i++)
    {
        delay_us(11000);   //44-48ms
    }

}*/
void DELAY(int z)//延时zms 44 z us
{
    int x, y;
    for (x = z; x > 0; x--)
        for (y = 110; y > 0; y--);
}
void I2C_delay(void)
{
    uint8_t i = 100; //50
    while (i)
    {
        i--;
    }
}

uint8_t I2C_Start(void)
{
    I2CSDA_H; // PIO0_11
    I2CSCL_H; // PIO0_10
    I2C_delay();
    if (!Chip(11)) // PIO0_11
        return FALSE;	//SDAÏßÎªµÍµçÆ½Ôò×ÜÏßÃ¦,ÍË³ö

    I2CSDA_L;
    I2C_delay();
    if (Chip(11)) // PIO0_11
        return FALSE;	//SDAÏßÎª¸ßµçÆ½Ôò×ÜÏß³ö´í,ÍË³ö

    I2CSDA_L;
    I2C_delay();
    return TRUE;
}

void I2C_Stop(void)
{
    I2CSCL_L;
    I2C_delay();

    I2CSDA_L;
    I2C_delay();

    I2CSCL_H;
    I2C_delay();

    I2CSDA_H;
    I2C_delay();
}

void I2C_Ack(void)
{
    I2CSCL_L;
    I2C_delay();
    I2CSDA_L;
    I2C_delay();
    I2CSCL_H;
    I2C_delay();
    I2CSCL_L;
    I2C_delay();
}

void I2C_NoAck(void)
{
    I2CSCL_L;
    I2C_delay();
    I2CSDA_H;
    I2C_delay();
    I2CSCL_H;
    I2C_delay();
    I2CSCL_L;
    I2C_delay();
}

uint8_t I2C_WaitAck(void) 	 //·µ»ØÎª:=1ÓÐACK,=0ÎÞACK
{
    I2CSCL_L;
    I2C_delay();
    I2CSDA_H;
    I2C_delay();
    I2CSCL_H;
    I2C_delay();
    if (Chip(11))
    {
        I2CSCL_L;
        return FALSE;
    }
    I2CSCL_L;
    return TRUE;
}


void EEP_MemoryReset(void)
{
    uint8_t i = 9;
    I2CSDA_H;
    I2CSCL_H;
    I2C_delay();
    I2C_delay();

    while (i--)
    {
        I2CSCL_L;
        I2C_delay();
        I2C_delay();

        I2CSCL_H;
        I2C_delay();
        I2C_delay();
    }
    I2C_Start();
}


void EEP_SoftReset(void)
{
    uint8_t i = 9;
    I2CSDA_H;
    I2CSCL_H;
    I2C_Start();

    while (i--)
    {
        I2CSCL_L;
        I2C_delay();
        I2C_delay();

        I2CSCL_H;
        I2C_delay();
        I2C_delay();
    }
    I2C_Start();
    I2C_Stop();
}

void I2C_SendByte(uint8_t SendByte) //Êý¾Ý´Ó¸ßÎ»µ½µÍÎ»//
{
    uint8_t i = 8;
    while (i--)
    {
        I2CSCL_L;
        I2C_delay();
        if (SendByte & 0x80)
            I2CSDA_H;
        else
            I2CSDA_L;
        SendByte <<= 1;
        I2C_delay();

        I2CSCL_H;
        I2C_delay();

    }
    I2CSCL_L;
}

uint8_t I2C_ReceiveByte(void)  //Êý¾Ý´Ó¸ßÎ»µ½µÍÎ»//
{
    uint8_t i = 8;
    uint8_t ReceiveByte = 0;

    I2CSDA_H;
    while (i--)
    {
        ReceiveByte <<= 1;
        I2CSCL_L;
        I2C_delay();
        //  I2C_delay();

        I2CSCL_H;
        I2C_delay();
        if (Chip(11))
        {
            ReceiveByte |= 0x01;
        }
        //   I2C_delay();
    }
    I2CSCL_L;
    return ReceiveByte;
}

//Ð´Èë1×Ö½ÚÊý¾Ý       ´ýÐ´ÈëÊý¾Ý    ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_WriteByte(uint8_t SendByte, uint16_t WriteAddress, uint8_t DeviceAddress)
{
    if (!I2C_Start())
        return FALSE;
    I2C_SendByte(((WriteAddress & 0x0700) >> 7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if (!I2C_WaitAck())
    {
        I2C_Stop();
        return FALSE;
    }

    I2C_SendByte((uint8_t)(WriteAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
    I2C_WaitAck();

    I2C_SendByte(SendByte);
    I2C_WaitAck();

    I2C_Stop();
    //×¢Òâ£ºÒòÎªÕâÀïÒªµÈ´ýEEPROMÐ´Íê£¬¿ÉÒÔ²ÉÓÃ²éÑ¯»òÑÓÊ±·½Ê½(10ms)
    delay_ms(5);
    return TRUE;
}

//×¢Òâ²»ÄÜ¿çÒ³Ð´
//Ð´Èë1´®Êý¾Ý      ´ýÐ´ÈëÊý×éµØÖ·    ´ýÐ´Èë³¤¶È      ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_BufferWrite(uint8_t* pBuffer, uint16_t length, uint16_t WriteAddress, uint8_t DeviceAddress)
{
    if (!I2C_Start())
        return FALSE;
    I2C_SendByte(((WriteAddress & 0x0700) >> 7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if (!I2C_WaitAck())
    {
        I2C_Stop();
        return FALSE;
    }

    I2C_SendByte((uint8_t)(WriteAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
    I2C_WaitAck();

    while (length--)
    {
        I2C_SendByte(*pBuffer);
        I2C_WaitAck();
        pBuffer++;
    }

    I2C_Stop();
    //×¢Òâ£ºÒòÎªÕâÀïÒªµÈ´ýEEPROMÐ´Íê£¬¿ÉÒÔ²ÉÓÃ²éÑ¯»òÑÓÊ±·½Ê½(10ms)
    delay_ms(5);
    return TRUE;
}


//¿çÒ³Ð´Èë1´®Êý¾Ý  ´ýÐ´ÈëÊý×éµØÖ·    ´ýÐ´Èë³¤¶È      ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_PageWrite(uint8_t* pBuffer, uint16_t length, uint16_t WriteAddress, uint8_t DeviceAddress)
{
    uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
    Addr = WriteAddress % I2C_PageSize;      //Ð´ÈëµØÖ·ÊÇ¿ªÊ¼Ò³µÄµÚ¼¸Î»
    count = I2C_PageSize - Addr;					    //ÔÚ¿ªÊ¼Ò³ÒªÐ´ÈëµÄ¸öÊý
    NumOfPage = length / I2C_PageSize;     //ÒªÐ´ÈëµÄÒ³Êý
    NumOfSingle = length % I2C_PageSize;     //²»×ãÒ»Ò³µÄ¸öÊý

    if (Addr == 0)         //Ð´ÈëµØÖ·ÊÇÒ³µÄ¿ªÊ¼
    {
        if (NumOfPage == 0)  //Êý¾ÝÐ¡ÓÚÒ»Ò³
        {
            I2C_BufferWrite(pBuffer, NumOfSingle, WriteAddress, DeviceAddress);   //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
        }
        else		            //Êý¾Ý´óÓÚµÈÓÚÒ»Ò³
        {
            while (NumOfPage)//ÒªÐ´ÈëµÄÒ³Êý
            {
                I2C_BufferWrite(pBuffer, I2C_PageSize, WriteAddress, DeviceAddress);//Ð´Ò»Ò³µÄÊý¾Ý
                WriteAddress += I2C_PageSize;
                pBuffer += I2C_PageSize;
                NumOfPage--;
                delay_ms(5);
            }
            if (NumOfSingle != 0)//Ê£ÓàÊý¾ÝÐ¡ÓÚÒ»Ò³
            {
                I2C_BufferWrite(pBuffer, NumOfSingle, WriteAddress, DeviceAddress); //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
                delay_ms(5);
            }
        }
    }

    else                  //Ð´ÈëµØÖ·²»ÊÇÒ³µÄ¿ªÊ¼
    {
        if (NumOfPage == 0)   //Êý¾ÝÐ¡ÓÚÒ»Ò³
        {
            I2C_BufferWrite(pBuffer, NumOfSingle, WriteAddress, DeviceAddress);   //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
        }
        else                //Êý¾Ý´óÓÚµÈÓÚÒ»Ò³
        {
            length -= count;
            NumOfPage = length / I2C_PageSize;  //ÖØÐÂ¼ÆËãÒªÐ´ÈëµÄÒ³Êý
            NumOfSingle = length % I2C_PageSize;  //ÖØÐÂ¼ÆËã²»×ãÒ»Ò³µÄ¸öÊý

            if (count != 0)
            {
                I2C_BufferWrite(pBuffer, count, WriteAddress, DeviceAddress);      //½«¿ªÊ¼µÄ¿Õ¼äÐ´ÂúÒ»Ò³
                WriteAddress += count;
                pBuffer += count;
            }

            while (NumOfPage--)  //ÒªÐ´ÈëµÄÒ³Êý
            {
                I2C_BufferWrite(pBuffer, I2C_PageSize, WriteAddress, DeviceAddress);//Ð´Ò»Ò³µÄÊý¾Ý
                WriteAddress += I2C_PageSize;
                pBuffer += I2C_PageSize;
            }
            if (NumOfSingle != 0)//Ê£ÓàÊý¾ÝÐ¡ÓÚÒ»Ò³
            {
                I2C_BufferWrite(pBuffer, NumOfSingle, WriteAddress, DeviceAddress); //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
            }
        }
    }
    return TRUE;
}

//¶Á³ö1´®Êý¾Ý         ´æ·Å¶Á³öÊý¾Ý  ´ý¶Á³ö³¤¶È      ´ý¶Á³öµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_ReadByte(uint8_t* pBuffer, uint16_t length, uint16_t ReadAddress, uint8_t DeviceAddress)
{
    if (!I2C_Start())
        return FALSE;
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if (!I2C_WaitAck())
    {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((uint8_t)(ReadAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
    I2C_WaitAck();

    I2C_Start();
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | DeviceAddress | 0x0001);
    I2C_WaitAck();
    while (length)
    {
        *pBuffer = I2C_ReceiveByte();
        if (length == 1)
            I2C_NoAck();
        else
            I2C_Ack();
        pBuffer++;
        length--;
    }
    I2C_Stop();
    delay_ms(5);
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//延时函数
void AD7416_delay()
{
    unsigned int i = 60;
    while (i--);
}
/*--------------------------------------------------------------------------------
调用方式：void AD7416_I2CStart(void) ﹫2001/07/0 4
函数说明：私有函数，I2C专用
---------------------------------------------------------------------------------*/
void AD7416_I2CStart(void)
{
    //EA=0;
    I2CSDA_H; I2CSCL_H; AD7416_delay();//INI
    I2CSDA_L; AD7416_delay();//START
    I2CSCL_L; AD7416_delay();
}
/*--------------------------------------------------------------------------------
调用方式：void AD7416_I2CStop(void) ﹫2001/07/0 4
函数说明：私有函数，I2C专用
---------------------------------------------------------------------------------*/
void AD7416_I2CStop(void)
{
    I2CSCL_L; I2CSDA_L; AD7416_delay();//INI
    I2CSCL_H; AD7416_delay();//STOP
    //EA=1;
}
uint8_t AD7416_WaitAck(void)
{
    unsigned char errtime = 255;//因故障接收方无ACK，超时值为255。
    I2CSDA_H; AD7416_delay();
    I2CSCL_H; AD7416_delay();
    AD7416_SystemError = 0x10;
    while (Chip(11))
    {
        errtime--;
        if (!errtime)
        {
            AD7416_I2CStop();
            AD7416_SystemError = 0x11;
            return FALSE;
        }
    }
    I2CSCL_L; AD7416_delay();
    return TRUE;
}
void AD7416_SendNotAck(void)
{
    I2CSDA_H; AD7416_delay();
    I2CSCL_H; AD7416_delay();
    I2CSCL_L; AD7416_delay();
}
void AD7416_I2CSendByte(unsigned char ch)
{
    unsigned char i = 8;
    while (i--)
    {
        I2CSCL_L;
        _nop_();
        AD7416_delay();
        //SDA_PIN=(bit)(ch&0x80); ch<<=1; AD7416_delay();

        if (ch & 0x80)
            I2CSDA_H;
        else
            I2CSDA_L;
        ch <<= 1;
        I2C_delay();
        I2CSCL_H; AD7416_delay();
    }
    I2CSCL_L; AD7416_delay();
}
unsigned char AD7416_I2CReceiveByte(void)
{
    unsigned char i = 8;
    unsigned char dat = 0;
    I2CSDA_H;
    while (i--)
    {
        dat <<= 1;
        I2CSCL_L; AD7416_delay();
        I2CSCL_H; AD7416_delay();
        dat |= I2CSDA_PIN;
    }
    I2CSCL_L; AD7416_delay();
    return(dat);
}
/*--------------------------------------------------------------------------
ACK BY MASTER 有CPU给传感器一个低，所以这个ACK是来自CPU的。
---------------------------------------------------------------------------*/
void AD7416_bitout()
{
    I2CSDA_L; AD7416_delay();
    I2CSCL_L; AD7416_delay();
    I2CSDA_L; AD7416_delay();
    I2CSCL_H; AD7416_delay();
    I2CSCL_L; AD7416_delay();
}
unsigned int Read7416(unsigned char address)
{
    unsigned char h, l, temp, c;
    unsigned int wendu;

    AD7416_I2CStart();
    AD7416_I2CSendByte(address); //写
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x00); //指向温度寄存器
    AD7416_SendNotAck();
    AD7416_I2CStop();

    AD7416_I2CStart();
    AD7416_I2CSendByte(address + 1); //读
    AD7416_WaitAck();
    h = AD7416_I2CReceiveByte(); //读高8位
    AD7416_bitout(); //CUP送低
    l = AD7416_I2CReceiveByte(); //读低8位
    AD7416_SendNotAck();
    AD7416_I2CStop();

    c = 2; //循环两次
    wendu = h; temp = l;
    //将高8位和低8位的前2位连接
    while (c--)
    {
        if (temp & 0x80)
        {
            wendu <<= 1;
            wendu |= 0x0001;
        }
        else
        {
            wendu <<= 1;
        }
    }
    //判断温度正负
    if (h & 0x80) //负
    {
        wendu = wendu - 0x01;
        wendu = ~wendu; //变回原码
        wendu = wendu & 0x03FF;
        wendu = wendu * 0.25;
        Temperature = wendu;
        ZorF = 0;
    }
    else //正
    {
        wendu = wendu * 0.25;
        Temperature = wendu;
        ZorF = 1;
    }
    return Temperature;
}
/////////////////////////////////////////////////////自己加的/////////////////////////////////////////////////////////

unsigned int Read741611(unsigned char address)
{
    unsigned char h, l, temp, c;
    unsigned int wendu;

    if (!I2C_Start())return FALSE;
    I2C_SendByte(0x90); //128,   // sensor I2C address + write bit
    if (!I2C_WaitAck())
    {
        I2C_Stop(); return FALSE;
    }
    I2C_SendByte(0x00);     // 0xF3TRIG_T_MEASUREMENT_POLL
    I2C_WaitAck();
    delay_us(20);
    I2C_Stop();
    do
    {
        DELAY(100);
        I2C_Start();
        I2C_SendByte(0x91);
    } while (!I2C_WaitAck());
    h = I2C_ReceiveByte();
    //	printf("%c\r\n",Tdata[0]);
    I2C_Ack();
    l = I2C_ReceiveByte();
    //	printf("%c\r\n",Tdata[1]);

    I2C_NoAck();
    I2C_Stop();

    c = 2; //循环两次
    wendu = h; temp = l;
    //将高8位和低8位的前2位连接
    while (c--)
    {
        if (temp & 0x80)
        {
            wendu <<= 1;
            wendu |= 0x0001;
        }
        else
        {
            wendu <<= 1;
        }
    }
    //判断温度正负
    if (h & 0x80) //负
    {
        wendu = wendu - 0x01;
        wendu = ~wendu; //变回原码
        wendu = wendu & 0x03FF;
        wendu = wendu * 0.25;
        Temperature = wendu;
        ZorF = 0;
    }
    else //正
    {
        wendu = wendu * 0.25;
        Temperature = wendu;
        ZorF = 1;
    }
    return Temperature;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//设定7416的OTI和HYST
/*----------------------------------------------------------------------------
OTI为上限 HYST为下限
7416做为恒温器使用 OTI必须低有效。当温度高于OTI值时由OTI脚发出低，直到温度低于
HYST值OTI脚才发出高。
-----------------------------------------------------------------------------*/
void Setup7416OTI(unsigned char OTI, unsigned char HYST, unsigned char address)
{

    unsigned char a, b;

    a = OTI; //温度转换
    a = a * 4;
    a >>= 2;

    b = HYST; //温度转换
    b = b * 4;
    b >>= 2;

    AD7416_I2CStart();
    AD7416_I2CSendByte(address); //写
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x01); //指向状态寄存器
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x18);
    AD7416_SendNotAck();
    AD7416_I2CStop();

    AD7416_I2CStart();
    AD7416_I2CSendByte(address); //写
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x03); //指向OTI存器
    AD7416_WaitAck();
    AD7416_I2CSendByte(a); //送温度高8位
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x00); //送温度低8位
    AD7416_SendNotAck();
    AD7416_I2CStop();


    AD7416_I2CStart();
    AD7416_I2CSendByte(address); //写
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x02); //指向HYST寄存器
    AD7416_WaitAck();
    AD7416_I2CSendByte(b); //送温度高8位
    AD7416_WaitAck();
    AD7416_I2CSendByte(0x00); //送温度低8位
    AD7416_SendNotAck();
    AD7416_I2CStop();
}

